package io.renren.modules.sp.controller;

import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.serializer.SerializerFeature;
import io.renren.common.annotation.LogOperation;
import io.renren.common.constant.Constant;
import io.renren.common.listener.SpMatchAreaLimitImportListener;
import io.renren.common.page.PageData;
import io.renren.common.redis.RedisUtils;
import io.renren.common.utils.DateUtils;
import io.renren.common.utils.DynamicHeadUtil;
import io.renren.common.utils.ExcelUtils;
import io.renren.common.utils.Result;
import io.renren.common.validator.AssertUtils;
import io.renren.common.validator.ValidatorUtils;
import io.renren.common.validator.group.AddGroup;
import io.renren.common.validator.group.DefaultGroup;
import io.renren.common.validator.group.UpdateGroup;
import io.renren.modules.sp.dao.SpMatchAreaLimitDao;
import io.renren.modules.sp.dto.SpMatchAreaLimitDTO;
import io.renren.modules.sp.dto.SpMatchItemDTO;
import io.renren.modules.sp.dto.SpUserImport;
import io.renren.modules.sp.entity.SpMatchAreaLimitEntity;
import io.renren.modules.sp.entity.TAreaEntity;
import io.renren.modules.sp.excel.SpMatchAreaLimitExcel;
import io.renren.modules.sp.service.SpMatchAreaLimitService;
import io.renren.modules.sp.service.SpMatchItemService;
import io.renren.modules.sp.service.SpMatchService;
import io.renren.modules.sp.service.TAreaService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpServletResponse;
import java.net.URLEncoder;
import java.util.*;
import java.util.stream.Collectors;


/**
* 赛事省份人数限制
*
* @author whc 1@1.com
* @since 3.0 2025-01-22
*/
@RestController
@RequestMapping("sp/spmatcharealimit")
@Api(tags="赛事省份人数限制")
public class SpMatchAreaLimitController {
    @Autowired
    RedisUtils redisUtils;
    @Autowired
    private SpMatchAreaLimitService spMatchAreaLimitService;
    @Autowired
    private TAreaService tAreaService;
    @Autowired
    private SpMatchService spamAreaService;
    @Autowired
    private SpMatchItemService spMatchItemService;
    @Autowired
    private SpMatchAreaLimitDao spMatchAreaLimitDao;

    @GetMapping("page")
    @ApiOperation("分页")
    @ApiImplicitParams({
            @ApiImplicitParam(name = Constant.PAGE, value = "当前页码，从1开始", paramType = "query", required = true, dataType = "int"),
            @ApiImplicitParam(name = Constant.LIMIT, value = "每页显示记录数", paramType = "query", required = true, dataType = "int"),
            @ApiImplicitParam(name = Constant.ORDER_FIELD, value = "排序字段", paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = Constant.ORDER, value = "排序方式，可选值(asc、desc)", paramType = "query", dataType = "String")
    })
    @RequiresPermissions("sp:spmatcharealimit:page")
    public Result<PageData<SpMatchAreaLimitDTO>> page(@ApiIgnore @RequestParam Map<String, Object> params) {
        PageData<SpMatchAreaLimitDTO> page = spMatchAreaLimitService.page(params);
        for (SpMatchAreaLimitDTO dto : page.getList()) {
            //省份名称
            TAreaEntity areaEntity = tAreaService.getByCode(dto.getProvince());
            dto.setProvinceName(areaEntity.getName());
            //赛项名称
            Integer matchItemId = dto.getMatchItemId();
            if (matchItemId != null) {
                Map<String, Object> map = spMatchItemService.queryBymatchItemId(matchItemId.longValue());
                if (map != null) {
                    dto.setMatchItemName(map.get("item_name").toString());
                    dto.setMatchName(map.get("match_name").toString());
                }
            }
        }
        return new Result<PageData<SpMatchAreaLimitDTO>>().ok(page);
    }
    @RequiresPermissions("sp:spmatcharealimit:page")
    @RequestMapping ("/page2")
    public Result<PageData<SpMatchAreaLimitDTO>> page2(@ApiIgnore @RequestParam Map<String, Object> params) {
        PageData<SpMatchAreaLimitDTO> page = spMatchAreaLimitService.matchItemPage(params);
        // 循环page
        List<SpMatchAreaLimitDTO> list = page.getList();
        for (SpMatchAreaLimitDTO spMatchItemDTO : list) {
            Map<String,Object> total = spMatchItemService.itemTotal(spMatchItemDTO.getMatchItemId().longValue(), "pass");
            spMatchItemDTO.setTotal(total);
            int tuijianNum = spMatchAreaLimitDao.queryUserNum(spMatchItemDTO.getMatchItemId());
            if(spMatchItemDTO!=null && spMatchItemDTO.getNum() != null) {
                spMatchItemDTO.setTuijianNum(spMatchItemDTO.getNum() - tuijianNum);
            }
        }
        return new Result<PageData<SpMatchAreaLimitDTO>>().ok(page);
    }

    @GetMapping("{id}")
    @ApiOperation("信息")
    @RequiresPermissions("sp:spmatcharealimit:info")
    public Result<SpMatchAreaLimitDTO> get(@PathVariable("id") Long id) {
        SpMatchAreaLimitDTO data = spMatchAreaLimitService.get(id);

        return new Result<SpMatchAreaLimitDTO>().ok(data);
    }

    @PostMapping
    @ApiOperation("保存")
    @LogOperation("保存")
    @RequiresPermissions("sp:spmatcharealimit:save")
    public Result save(@RequestBody SpMatchAreaLimitDTO dto) {
        //效验数据
        ValidatorUtils.validateEntity(dto, AddGroup.class, DefaultGroup.class);

        spMatchAreaLimitService.save(dto);

        return new Result();
    }

    @PutMapping
    @ApiOperation("修改")
    @LogOperation("修改")
    @RequiresPermissions("sp:spmatcharealimit:update")
    public Result update(@RequestBody SpMatchAreaLimitDTO dto) {
        //效验数据
        ValidatorUtils.validateEntity(dto, UpdateGroup.class, DefaultGroup.class);
        //校验是否超报名人数
        try {
            spMatchAreaLimitService.validateDate(dto);
        } catch (Exception e) {
            return new Result().error(e.getMessage());
        }
        if(dto.getId() != null){
            spMatchAreaLimitService.update(dto);
        }else if(dto.getNum() == null){
            spMatchAreaLimitService.deleteById( dto.getId());
        }else{
            spMatchAreaLimitService.toSave(dto);
        }

        return new Result();
    }

    @DeleteMapping
    @ApiOperation("删除")
    @LogOperation("删除")
    @RequiresPermissions("sp:spmatcharealimit:delete")
    public Result delete(@RequestBody Long[] ids) {
        //效验数据
        AssertUtils.isArrayEmpty(ids, "id");

        spMatchAreaLimitService.delete(ids);

        return new Result();
    }

    @GetMapping("export2")
    @ApiOperation("导出")
    @LogOperation("导出")
    @RequiresPermissions("sp:spmatcharealimit:export")
    public void export(@ApiIgnore @RequestParam Map<String, Object> params, HttpServletResponse response) throws Exception {
        List<SpMatchAreaLimitDTO> list = spMatchAreaLimitService.list(params);
        List<SpMatchAreaLimitExcel> excelList = new ArrayList<>();
        SpMatchAreaLimitExcel excel = null;
        for (SpMatchAreaLimitDTO dto : list) {
            excel = new SpMatchAreaLimitExcel();
            //省份名称
            //TAreaEntity areaEntity = tAreaService.getByCode(dto.getProvince());
            excel.setProvince(dto.getProvince());
            //赛项名称
            Integer matchItemId = dto.getMatchItemId();
            if (matchItemId != null) {
                Map<String, Object> map = spMatchItemService.queryBymatchItemId(matchItemId.longValue());
                if (map != null) {
                    excel.setMatchId(Integer.parseInt(map.get("match_id").toString()));
                    excel.setMatchName(map.get("match_name").toString());
                    excel.setMatchItemId(map.get("id").toString());
                    excel.setMatchItemName(map.get("item_name").toString());
                }
                excel.setId(dto.getId());
                excel.setNum(dto.getNum());
                excelList.add(excel);
            }
        }
        ExcelUtils.exportExcelToTarget(response, null, "赛事省份人数限制", excelList, SpMatchAreaLimitExcel.class);
    }


    /**
     * 超管可针对赛事（到赛项），对某省份进行晋级名额限制（省赛晋级和市赛直通均属于其内），超额时无法点击推荐晋级/推荐直通
     * 名额分配限制，可导出表格报表，也可利用表格反向导入进行配置
     */

    /**
     * 导入
     *
     * @param file
     * @return
     * @throws Exception
     */
    @PostMapping("import")
    @ApiImplicitParam(name = "file", value = "文件", paramType = "query", dataType = "file")
    public Result importCertificate(@RequestParam("file") MultipartFile file) throws Exception {
        Result result = new Result();
        List<Map<Integer, String>> list = new ArrayList<>();
        //获取年份 1. 查询数据
        String year = DateUtils.getYear();
        List<Map<String, String>> dataList = spMatchAreaLimitService.querySpMatchLimit(year);

        //大批量excel数据导入
        EasyExcel.read(file.getInputStream(), new SpMatchAreaLimitImportListener(spMatchAreaLimitService, result, list, dataList)).sheet().doRead();
        boolean flag = false;
        for (Map<Integer, String> item : list) {
            if ("导入失败".equals(item.get(item.size() - 1))) {
                flag = true;
                //移除最后一列
                item.remove(item.size() - 1);
            }
        }
        if (flag) {
            String errorCode = UUID.randomUUID().toString();
            String json = JSON.toJSONString(
                    list,
                    SerializerFeature.WriteMapNullValue  // 关键：强制保留 null
            );
            redisUtils.set(errorCode, json, 1000);
            return new Result().ok(errorCode);
        }
        return result;
    }

    @GetMapping("exportError1")
    public void export1(String errorCode, HttpServletResponse response) throws Exception {
        String json = (String) redisUtils.get(errorCode);
        redisUtils.delete(errorCode);
        if (json != null) {
            //获取数据
            // 方法 1：使用 TypeReference + Feature
            List<Map> list = JSON.parseObject(
                    json,
                    new TypeReference<List<Map>>() {},
                    Feature.IgnoreNotMatch
            );
            for(Map item:list){
                System.out.println( item.size());
            }
            //获取表头
            Map head = list.get(list.size()-1);
            //移除表头
            list.remove(list.size()-1);
            List headList = new ArrayList<>();
            for(int i=0;i<head.size();i++){
                headList.add(Collections.singletonList(head.get(i)));
            }
            //headList之后一列是否是失败原因
            if(!"失败原因".equals(head.get(head.size()-1))){
                headList.add(Collections.singletonList("失败原因"));
            }
            // 3. 设置响应头
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            String fileName = URLEncoder.encode("赛事省份人数限制", "UTF-8").replaceAll("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");

            // 5. 导出Excel
            EasyExcel.write(response.getOutputStream())
                    .head(headList)
                    .sheet("赛事省份人数限制")
                    .doWrite(list);
        }
    }


    /**
     * 导出动态表格
     */
    @RequestMapping("/export")
    public void exportSign(HttpServletResponse response, Integer matchId) throws Exception {
        // 1. 查询数据
        List<SpMatchAreaLimitEntity> dataList = spMatchAreaLimitService.findByMatchId(matchId);

        // 2. 获取所有赛项ID
        List<String> matchItemIds = dataList.stream()
                .map(SpMatchAreaLimitEntity::getMatchItemName)
                .distinct()
                .sorted()
                .collect(Collectors.toList());

        // 3. 设置响应头
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        String fileName = URLEncoder.encode("赛事省份人数限制", "UTF-8").replaceAll("\\+", "%20");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");

        // 4. 构建动态表头和数据
        List<List<String>> headers = DynamicHeadUtil.buildDynamicHeaders(matchItemIds);
        List<List<Object>> dynamicData = DynamicHeadUtil.buildDynamicData(dataList, matchItemIds);

        // 5. 导出Excel
        EasyExcel.write(response.getOutputStream())
                .head(headers)
                .sheet("赛事省份人数限制")
                .doWrite(dynamicData);
    }

    /**
     * 导出动态表格
     */
    @RequestMapping("/exportLimit")
    public void exportSign2(HttpServletResponse response) throws Exception {
        //获取年份 1. 查询数据
        String year = DateUtils.getYear();
        List<Map<String,String>> dataList = spMatchAreaLimitService.querySpMatchLimit3(year);

        Set<String> matchIds = new LinkedHashSet<>();
        Set<String> itemIds = new LinkedHashSet<>();
        Map<String,String> numMap = new HashMap<>();
        for (Map<String, String> map : dataList) {
            String matchName = map.get("match_name");
            String privince = map.get("name");
            String matchItem = map.get("item_name");
            String num = map.get("num");
            matchIds.add(matchName+"@@"+privince);
            itemIds.add(matchItem);
            numMap.put(matchName+"@@"+privince+"@@"+matchItem,num);
        }
        //head 赛事-赛项-省份-限制人数
        List<List<String>> headers = new ArrayList<>();
        headers.add(Collections.singletonList("赛事"));
        headers.add(Collections.singletonList("省份"));
        for (String itemId : itemIds) {
            headers.add(Collections.singletonList(itemId));
        }
        //数据
        List<List<Object>> dynamicData = new ArrayList<>();
        for (String matchId : matchIds) {
            List<Object> row = new ArrayList<>();
            row.add(matchId.split("@@")[0]);
            row.add(matchId.split("@@")[1]);
            for (String itemId : itemIds) {
                String num = numMap.get(matchId+"@@"+itemId);
                if(num==null){
                    num ="-";
                }
                row.add(num);
            }
            dynamicData.add(row);
        }

        // 3. 设置响应头
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        String fileName = URLEncoder.encode("赛事省份人数限制", "UTF-8").replaceAll("\\+", "%20");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
        EasyExcel.write(response.getOutputStream())
                .head(headers)
                .sheet("赛事省份人数限制")
                .doWrite(dynamicData);
    }




    /**
     * 模板下载
     */
    @RequestMapping("/download")
    public void download(HttpServletResponse response, Integer matchId) throws Exception {
        // 1. 查询数据
        List<String> dataList = spMatchAreaLimitService.productList();

        // 2. 获取所有赛项ID
        List<String> headerList = spMatchAreaLimitService.headerList(matchId);

        // 3. 设置响应头
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        String fileName = URLEncoder.encode("赛事省份人数限制", "UTF-8").replaceAll("\\+", "%20");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");

        // 4. 构建动态表头和数据
        List<List<String>> headers = DynamicHeadUtil.buildDynamicHeaders(headerList);
        //第一列的值用dataList来填充，其他用 0 填充
        List<List<Object>> dynamicData = new ArrayList<>();
        for (String data : dataList) {
            List<Object> object = new ArrayList<>();
            object.add(data);
            for (int i = 0; i < headerList.size(); i++) {
                object.add(0);
            }
            dynamicData.add(object);
        }
        // 5. 导出Excel
        EasyExcel.write(response.getOutputStream())
                .head(headers)
                .sheet("赛事省份人数限制")
                .doWrite(dynamicData);
    }


}
